import CodeBlock from '@theme/CodeBlock'
import BrowserOnly from '@docusaurus/BrowserOnly'
import { PropsTable } from '@site/src/components/PropsTable'
import { generateDataRecords } from '../utils/data'
import { XYWrapper, XYWrapperWithInput, axis } from '../wrappers/xy-wrapper'
import { Brush } from '@unovis/ts'

export const brushProps = (showAxis = true) => ({
    name: "Brush",
    height: 75,
    components: [{
        name: showAxis ? 'StackedBar' : 'Area',
        props: {
          x: d => d.x,
          y: d => d.y,
        },
        key: "components",
      },
    ].concat(showAxis ? axis('x') : []),
    data: generateDataRecords(30)
})

## Basic Configuration
_Brush_ is designed to work inside an _XYContainer_ alongside an _XYChart_. The basic configuration looks like:
<XYWrapper {...brushProps(false)} showContext="full"/>

## Usage
The _Brush_ component has four event listener properties:

- `onBrushStart`
- `onBrushMove`
- `onBrushEnd`
- `onBrush`, which encapsulates all the above.

Each callback has the following parameters:
- _selection_: type `[number, number]`, the range of data current being displayed
- _event_ - the brush event instance
- _userDriven_: type `boolean`, to indicate whether the event was triggered by the user

<BrowserOnly>
  {() => {
    const { Tooltip } = require('@unovis/ts')
    const tooltip = new Tooltip({})
    const action = (i) => `(selection, event, userDriven) => {\n    if (userDriven) {\n      ${i}\n    }\n  }`
    return (
      <XYWrapper {...brushProps()}
        height={150}
        containerProps={{ tooltip }}
        onBrushStart={(selection, event, userDriven) => userDriven && tooltip.place({ x: 0, y: 0 })}
        onBrushMove={(selection, event, userDriven) => userDriven && tooltip.show(selection)}
        onBrushEnd={(selection, event, userDriven) => userDriven && tooltip.hide()}
        showContext="container"
        declarations={{
          tooltip: 'new Tooltip({})',
          onBrushStart: action('tooltip.place({ x: 0, y: 0 }}'),
          onBrushMove: action('tooltip.show(selection)'),
          onBrushEnd: action('tooltip.hide()')
        }}
        imports={{"unovis/ts": ["Tooltip"]}}
      />
    )
  }}
</BrowserOnly>

## Selections
### Manual Selection
You can explicitly define the default selection range using the `selection` property:
<XYWrapper {...brushProps()} selection={[3,6]}/>

### Selection Min Length
You can set a constraint for the minimum `selection` value with the `selectionMinLength` property:
<XYWrapper {...brushProps()} selectionMinLength={5}/>

### Draggable
By default, setting the desired the range relies on moving both start and end _Brush_ handles. You can adjust the entire range with one click by enabling the `draggable` proprerty:
<XYWrapper {...brushProps()} height={200} selectionMinLength={2} selection={[3,6]} draggable={true}/>

## Brush Appearance
### Handle Position
`handlePosition` changes the placement of the _Brush_ handle with respect to the _XYChart_.
<XYWrapperWithInput {...brushProps()} containerProps={{ margin: { top: 0, bottom: 0, left: 10, right: 10 }}} property="handlePosition" inputType="select" options={['outside', 'inside']}/>

### Handle Width
`handleWidth` sets the width in pixels of the _Brush_'s handle:
<XYWrapperWithInput {...brushProps()} property="handleWidth" inputType="range" defaultValue={20}/>

### Selection
You can change the appearance of the selection by changing the corresponding CSS variables.
For example, here's how you can modify the appearance of the selected and unselected areas:

<CodeBlock language="css">
{`--vis-brush-selection-fill-color: #0b1640;
--vis-brush-selection-opacity: 0.6;
--vis-brush-unselected-fill-color: #fff;
--vis-brush-unselected-opacity: 0.9;
`}</CodeBlock>

<div style={{
  '--vis-brush-selection-fill-color': '#0b1640',
  '--vis-brush-selection-opacity': '0.6',
  '--vis-brush-unselected-fill-color': '#fff',
  '--vis-brush-unselected-opacity': '0.9',
  }}>
  <XYWrapper {...brushProps()} selection={[2,5]}/>
</div>


## CSS Variables
<details open>
  <summary>Supported CSS variables and their default values</summary>
  <CodeBlock language="css">
{`${
  Object.entries(Brush.selectors.cssVarDefaults)
  .map(([key, value]) => `${key}: ${value};`).join('\n')}
`}</CodeBlock>
</details>

## Component Props
<PropsTable name='VisBrush'></PropsTable>
